import React, { memo, useEffect, useRef, useState } from 'react'

import { View } from '@tarojs/components'

import styles from './index.module.scss'

// #region 书写注意
//
// 目前 typescript 版本还无法在装饰器模式下将 Props 注入到 Taro.Component 中的 props 属性
// 需要显示声明 connect 的参数类型并通过 interface 的方式指定 Taro.Component 子类的 props
// 这样才能完成类型检查和 IDE 的自动提示
// 使用函数模式则无此限制
// ref: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/20796
//
// #endregion

type PageStateProps = {}

type PageDispatchProps = {}

type PageOwnProps = {}

type PageState = {}

type IProps = PageStateProps & PageDispatchProps & PageOwnProps & PageState

interface Index {
  props: IProps
}

const Index: React.FC<IProps> = memo(
  () => {
    const [date, setDate] = useState<Date>(new Date())

    // ================= React的Hook ======================
    // 使用 useEffect 模拟 componentDidMount componentWillUnmount
    // componentWillMount： 在渲染前调用,在客户端也在服务端。
    // componentDidMount： 在第一次渲染后调用，只在客户端。
    //                     之后组件已经生成了对应的DOM结构，可以通过this.getDOMNode()来进行访问。
    //                     如果你想和其他JavaScript框架一起使用
    //                     可以在这个方法中调用setTimeout, setInterval或者发送AJAX请求等操作(防止异步操作阻塞UI)。
    useEffect(() => {
      console.log('componentDidMount!')
      const timerID = setInterval(() => setDate(new Date()), 1000)
      return () => {
        console.log('componentWillUnmount!')
        clearInterval(timerID)
      }
    }, [])

    // 使用 useEffect 模拟 componentDidUpdate
    // componentDidUpdate：在组件完成更新后立即调用。在初始化时不会被调用。
    const mounted = useRef<boolean>(false)
    useEffect(() => {
      if (!mounted.current) {
        mounted.current = true
      } else {
        console.log('componentDidUpdate')
      }
    })

    // ================= 小程序特有的Hook ======================
    return (
      <View>
        <van-divider />
        <van-notice-bar
          color='#1989fa'
          background='#ecf9ff'
          left-icon='volume-o'
          text={date.toLocaleTimeString()}
        />
      </View>
    )
  },
  (prevProps, nextProps) => {
    // 使用memo的第二个参数来模拟shouldComponentUpdate
    // 由于state已经有useState代替
    // 所以shouldComponentUpdate通过判断stata来决定是否更新页面，没有必要在memo
    // 完全可以通过自己控制相关的state
    console.log(prevProps)
    return false
  }
)

export default Index
